package com.googlecode.gwtCorsForIe8.client;

import java.util.HashMap;
import java.util.Map;

import com.google.gwt.core.client.JavaScriptException;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.RequestPermissionException;
import com.google.gwt.http.client.RequestTimeoutException;
import com.google.gwt.user.client.rpc.RpcRequestBuilder;

/**
 * Original from
 * http://experienceswithgwt.blogspot.com/2010/04/gwt-and-cross-site
 * -requests_28.html
 * 
 * @author Sebastian
 */
public class IECrossSiteRequestBuilder extends RequestBuilder {
	private Map<String, String> headers;

	public IECrossSiteRequestBuilder(RequestBuilder.Method httpMethod,
			String url) {
		super(httpMethod, url);
		this.headers = new HashMap<String, String>();
	}

	public Request send() throws RequestException {
		return doSend(getRequestData(), getCallback());
	}

	public Request sendRequest(String data, RequestCallback callback)
			throws RequestException {
		return doSend(data, callback);
	}

	@Override
	public void setHeader(String header, String value) {
		super.setHeader(header, value);
		this.headers.put(header, value);
	}

	private Request doSend(String data, final RequestCallback callback)
			throws RequestException {
		String prefix = "";
		for (Map.Entry<String, String> entry : this.headers.entrySet()) {
			String key = entry.getKey();
			// if (RpcRequestBuilder.STRONG_NAME_HEADER.equals(key)) {
			// key = "X-GP";
			// } else if (RpcRequestBuilder.MODULE_BASE_HEADER.equals(key)) {
			// key = "X-GMB";
			// } else if (RpcRequestBuilder.CONTENT_TYPE_HEADER.equals(key)) {
			// key = "ConType";
			// }
			prefix += ";" + key.replace(";", "\\;");
			prefix += ";" + entry.getValue().replace(";", "\\;");
		}
		// if (!append.isEmpty()) {
		// append = "?" + append.substring(1);
		// }
		System.out.println(getUrl());
		data = prefix.length()  + prefix + ";" + data;
		System.out.println(data);
		XDomainRequest xhr = XDomainRequest.create();
		try {
			xhr.open(getHTTPMethod(), getUrl());
		} catch (JavaScriptException e) {
			RequestPermissionException requestPermissionException = new RequestPermissionException(
					getUrl());
			requestPermissionException.initCause(new RequestException(e
					.getMessage()));
			throw requestPermissionException;
		}
		// Cannot set content type on IE
		final IECrossSiteRequest req = new IECrossSiteRequest(xhr);
		req.setStatus(IECrossSiteRequest.OPEN);
		final int timeout;
		if ((timeout = getTimeoutMillis()) > 0) {
			xhr.setTimeout(getTimeoutMillis());
		}
		// set handlers
		xhr.setHandler(new XDomainRequestHandler() {
			public void onLoad(XDomainRequest r) {
				req.setStatus(IECrossSiteRequest.DONE);
				callback.onResponseReceived(req, new IECrossSiteResponse(r));
			}

			public void onTimeout(XDomainRequest r) {
				req.setStatus(IECrossSiteRequest.DONE);
				callback.onError(req, new RequestTimeoutException(req, timeout));
			}

			public void onProgress(XDomainRequest r) {
			}

			public void onError(XDomainRequest r) {
				// Assume permission exception since XDomainRequest does not
				// return an error reason
				req.setStatus(IECrossSiteRequest.DONE);
				callback.onError(req, new RequestPermissionException(getUrl()));
			}
		});
		try {
			xhr.send(data);
			req.setStatus(IECrossSiteRequest.SENT);
		} catch (JavaScriptException e) {
			throw new RequestException(e.getMessage());
		}
		return req;
	}
}